#include "mfrc522_driver.h"
#include "FreeRTOS.h"
#include "task.h"

/* M1卡块C1 C2 C3 控制位 */
typedef struct
{
    uint8_t C1;
    uint8_t C2;
    uint8_t C3;
}Mifare_One_Ctrl_Bits_t;

static volatile uint32_t* MFRC522_RST_State;



/* 读寄存器 */
static uint8_t Read_NFC_One_Value(uint8_t reg)
{
    static uint8_t tx_buffer[2];
    static uint8_t rx_buffer[2];

    tx_buffer[0] = (reg << 1) | 0X80;
    tx_buffer[1] = 0;
    NFC_SPI_Start_TRx_Transmit(tx_buffer, rx_buffer, 2);
    return rx_buffer[1];
}
/* 写寄存器 */
static void Write_NFC_One_Value(uint8_t reg, uint8_t value)
{
    static uint8_t tx_buffer[2];

    tx_buffer[0] = (reg << 1) & 0X7E;
    tx_buffer[1] = value;
    NFC_SPI_Start_TRx_Transmit(tx_buffer, NULL, 2);
}



/* 设置寄存器位 */
static void MFRC522_Set_Bit_Mask(uint8_t reg, uint8_t mask)
{
    uint8_t temp;
    
    temp = Read_NFC_One_Value(reg);
    Write_NFC_One_Value(reg, temp | mask);
}
/* 清除寄存器位 */
static void MFRC522_Clr_Bit_Mask(uint8_t reg, uint8_t mask)
{
    uint8_t temp;
    
    temp = Read_NFC_One_Value(reg);
    Write_NFC_One_Value(reg, temp & (~mask));
}
/* 开启天线 */
static void MFRC522_Antenna_On(void)
{
    if (!(Read_NFC_One_Value(MFRC522_TxControlReg) & 0x03))
    {
        MFRC522_Set_Bit_Mask(MFRC522_TxControlReg, 0x03);
    }
}
/* 关闭天线 */
static void MFRC522_Antenna_Off(void)
{
    MFRC522_Clr_Bit_Mask(MFRC522_TxControlReg, 0x03);
}

/**
  * @brief  通过RC522和ISO14443卡通讯
  * @param  Command，RC522命令字
  * @param  InData，通过RC522发送到卡片的数据
  * @param  InLenByte，发送数据的字节长度
  * @param  OutData，接收到的卡片返回数据
  * @param  OutLenBit，返回数据的位长度
  * @retval 状态值= MI_OK，成功
  */
static uint8_t MFRC522_To_Card(uint8_t command, uint8_t* in_data, uint8_t in_len_byte, uint8_t* out_data, uint32_t* out_len_bit)
{
    uint8_t status = MI_ERR;
    uint8_t IrqEn;
    uint8_t WaitFor;
    uint8_t LastBits;
    uint8_t N;
    uint32_t i;

    switch ( command )
    {
    case MFRC522_PCD_AUTHENT:   //Mifare认证
        IrqEn   = 0x12;	        //允许错误中断请求ErrIEn  允许空闲中断IdleIEn
        WaitFor = 0x10;       	//认证寻卡等待时候 查询空闲中断标志位
        break;    
    case MFRC522_PCD_TRANSCEIVE://接收发送 发送接收
        IrqEn   = 0x77;	        //允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
        WaitFor = 0x30;	        //寻卡等待时候 查询接收中断标志位与 空闲中断标志位
        break;    
    default:
        return status;
    }

    // 保存当前中断使能状态
    uint8_t oldIrqEn = Read_NFC_One_Value(MFRC522_ComIEnReg);

    // 禁用中断进行同步通信
    //IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
    Write_NFC_One_Value(MFRC522_ComIEnReg, IrqEn | 0x80);
    //Set1该位清零时，CommIRqReg的屏蔽位清零
    MFRC522_Clr_Bit_Mask(MFRC522_ComIrqReg, 0x80);
    //写空闲命令
    Write_NFC_One_Value(MFRC522_CommandReg, MFRC522_PCD_IDLE);

    //置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
    MFRC522_Set_Bit_Mask(MFRC522_FIFOLevelReg, 0x80);
    for (i = 0; i < in_len_byte; i++)
    {
        Write_NFC_One_Value(MFRC522_FIFODataReg, in_data[i]); //写数据进FIFOdata
    }
    Write_NFC_One_Value(MFRC522_CommandReg, command);		//写命令
    if (command == MFRC522_PCD_TRANSCEIVE)
    {
        //StartSend置位启动数据发送 该位与收发命令使用时才有效
        MFRC522_Set_Bit_Mask(MFRC522_BitFramingReg,0x80);  
    }

    i = 5;                                  //根据时钟频率调整，操作M1卡最大等待时间25ms
    do 						                //认证与寻卡等待时间	
    {
        vTaskDelay(5 / portTICK_RATE_MS);
        N = Read_NFC_One_Value(MFRC522_ComIrqReg);		 //查询事件中断
        i--;
    } while ((i != 0) && (!(N & 0x01)) && (!(N & WaitFor)));	

    MFRC522_Clr_Bit_Mask(MFRC522_BitFramingReg, 0x80);	 //清理允许StartSend位

    if (i != 0)
    {
        //读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
        if (!(Read_NFC_One_Value(MFRC522_ErrorReg) & 0x1B))	
        {
            status = MI_OK;
            if (N & IrqEn & 0x01)				//是否发生定时器中断
                status = MI_NOTAGERR; 
        
            if (command == MFRC522_PCD_TRANSCEIVE)
            {
                //读FIFO中保存的字节数
                N = Read_NFC_One_Value(MFRC522_FIFOLevelReg);		          
                //最后接收到得字节的有效位数
                LastBits = Read_NFC_One_Value(MFRC522_ControlReg) & 0x07;	
        
                if (LastBits)
                    //N个字节数减去1（最后一个字节）+最后一位的位数 读取到的数据总位数
                    *out_len_bit = (N - 1) * 8 + LastBits;   	
                else
                    *out_len_bit = N * 8;      //最后接收到的字节整个字节有效
        
                if (N == 0)		
                    N = 1;    
                if (N > MFRC522_MAXRLEN)
                    N = MFRC522_MAXRLEN;  
                
                for ( i = 0; i < N; i ++ )
                {
                    out_data[i] = Read_NFC_One_Value(MFRC522_FIFODataReg);
                }
            }
        }
        else
            status = MI_ERR;  
    }
    /* 停止定时器 */
    MFRC522_Set_Bit_Mask(MFRC522_ControlReg, 0x80);
    // 恢复之前的中断使能状态
    Write_NFC_One_Value(MFRC522_ComIEnReg, oldIrqEn);
    return status;
}



/* 复位 */
void MFRC522_Restart(void)
{
    *MFRC522_RST_State = Low;
	vTaskDelay(10 / portTICK_RATE_MS);
    *MFRC522_RST_State = Hig;
	vTaskDelay(20 / portTICK_RATE_MS);

	Write_NFC_One_Value(MFRC522_CommandReg, MFRC522_PCD_RESETPHASE);
    while (Read_NFC_One_Value(MFRC522_CommandReg) & 0x10)
    {
        vTaskDelay(10 / portTICK_RATE_MS);
    }
	
	//定义发送和接收常用模式 和Mifare卡通讯，CRC初始值0x6363
    Write_NFC_One_Value(MFRC522_ModeReg, 0x3D);        
    Write_NFC_One_Value(MFRC522_TReloadRegL, 30);     //16位定时器低位    
	Write_NFC_One_Value(MFRC522_TReloadRegH, 0);      //16位定时器高位
    Write_NFC_One_Value(MFRC522_TModeReg, 0x8D);      //定义内部定时器的设置
    Write_NFC_One_Value(MFRC522_TPrescalerReg, 0x3E); //设置定时器分频系数
	Write_NFC_One_Value(MFRC522_TxAutoReg, 0x40);     //调制发送信号为100%ASK
		
}
/* 设置工作方式 */
void MFRC522_Set_ISP_Type(uint8_t type)
{
	if ( type == 'A')//ISO14443_A
    {
		MFRC522_Clr_Bit_Mask(MFRC522_Status2Reg, 0x08);
        Write_NFC_One_Value(MFRC522_ModeReg, 0x3D);         //3F
		Write_NFC_One_Value(MFRC522_RxSelReg, 0x86);        //84
		Write_NFC_One_Value(MFRC522_RFCfgReg, 0x7F);        //4F
		Write_NFC_One_Value(MFRC522_TReloadRegL, 30);        
		Write_NFC_One_Value(MFRC522_TReloadRegH, 0);
		Write_NFC_One_Value(MFRC522_TModeReg, 0x8D);
		Write_NFC_One_Value(MFRC522_TPrescalerReg, 0x3E);
		vTaskDelay(10 / portTICK_RATE_MS);
		MFRC522_Antenna_On();//开天线
    }
}
/* 清除中断 */
void MFRC522_Clr_IRQ_Flag(void)
{
    /* MFRC522 不支持自动寻到卡产生中断的 */
    Write_NFC_One_Value(MFRC522_ComIrqReg, 0xff);
}
/* 启用中断 */
void MFRC522_Set_IRQ_State(uint8_t state)
{
    /* MFRC522 不支持自动寻到卡产生中断的 */
    MFRC522_Clr_IRQ_Flag();
    if (state)
    {
        // RxIEn: 接收完成时触发中断
        // IdleIEn: 命令执行完成进入空闲状态时触发中断
        // TxIEn: 发送数据完成
        // 0x20=RxIEn, 0x10=IdleIEn， 0x40=TxIEn
        Write_NFC_One_Value(MFRC522_ComIEnReg, 0x10 | 0x20 | 0x40| 0x80);// 并设置IRQ引脚输出模式（低电平有效）
    }
    else
    {
        // 禁用所有中断
        Write_NFC_One_Value(MFRC522_ComIEnReg, 0x00 | 0x80);// 并设置IRQ引脚输出模式（低电平有效）
    }
}
/* 初始化 */
void MFRC522_Init(void)
{
    /*RST*/
    WHT_GPIO_BSP.WHT_Set_Clock(MFRC522_RST_GPIO_PORT, ENABLE);
    WHT_GPIO_BSP.WHT_Set_State(MFRC522_RST_GPIO_PORT, MFRC522_RST_GPIO_PIN, Hig);
    WHT_GPIO_BSP.WHT_Set_Mode(MFRC522_RST_GPIO_PORT, MFRC522_RST_GPIO_PIN, Mode_Out_PP);
    WHT_GPIO_BSP.WHT_Config_Bit_Output(MFRC522_RST_GPIO_PORT, MFRC522_RST_GPIO_PIN, &MFRC522_RST_State);
    /*IRQ*/
    /*SPI*/
    NFC_SPI_Init_Config();
    MFRC522_Restart();
}




/**
  * @brief 寻卡
  * @param  Req_code，寻卡方式 = 0x52，寻感应区内所有符合14443A标准的卡；
            寻卡方式= 0x26，寻未进入休眠状态的卡
  * @param  out_tag_type，卡片类型代码
  * @retval 状态值= MI_OK，成功
  */
uint8_t MFRC522_Request(uint8_t req_code, uint8_t* out_tag_type)
{
    uint8_t status;  
    uint8_t buffer[MFRC522_MAXRLEN]; 
    uint32_t backBits;

    //清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
    MFRC522_Clr_Bit_Mask(MFRC522_Status2Reg, 0x08);
	//发送的最后一个字节的 七位
    Write_NFC_One_Value(MFRC522_BitFramingReg, 0x07);
    //TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
    MFRC522_Set_Bit_Mask(MFRC522_TxControlReg, 0x03);

    buffer[0] = req_code;		//存入 卡片命令字
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 1, buffer, &backBits);//寻卡
    if ((status == MI_OK) && (backBits == 16))	//寻卡成功返回卡ATQA/SAK值
    {
        memcpy(out_tag_type, buffer, 3);
    }
    else
        status = MI_ERR;
    return status;
}

/* 防冲撞 获取卡UID*/
uint8_t MFRC522_Anticoll_Get_UID(uint8_t* out_uid)
{
    uint8_t status;
    uint8_t ucSnr_check = 0;
    uint8_t buffer[MFRC522_MAXRLEN]; 
    uint32_t backBits;
  
    //清MFCryptol On位 只有成功执行MFAuthent命令后，该位才能置位
    MFRC522_Clr_Bit_Mask(MFRC522_Status2Reg, 0x08);
    //清理寄存器 停止收发
    Write_NFC_One_Value(MFRC522_BitFramingReg, 0x00);	
	//清ValuesAfterColl所有接收的位在冲突后被清除
    MFRC522_Clr_Bit_Mask(MFRC522_CollReg, 0x80);			  
 
    buffer[0] = MFRC522_PICC_ANTICOLL1;	//卡片防冲突命令
    buffer[1] = 0x20;
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 2, buffer, &backBits);//与卡片通信

    if (status == MI_OK)
    {
        for (uint8_t i = 0; i < 4; i++)
        {
            out_uid[i] = buffer[i]; //读出UID
            ucSnr_check ^= buffer[i];
        }
        if (ucSnr_check != buffer[4])
            status = MI_ERR;
    }
    MFRC522_Set_Bit_Mask(MFRC522_CollReg, 0x80);   
    return status;
}

/**
  * @brief  用RC522计算CRC16
  * @param  Indata，计算CRC16的数组
  * @param  Len，计算CRC16的数组字节长度
  * @param  OutData，存放计算结果存放的首地址
  */
static void MFRC522_Calulate_CRC(uint8_t* in_data, uint8_t in_len_byte, uint8_t* out_data)
{
    uint8_t i, n;

    MFRC522_Clr_Bit_Mask(MFRC522_DivIrqReg, 0x04);
    Write_NFC_One_Value(MFRC522_CommandReg, MFRC522_PCD_IDLE);
    MFRC522_Set_Bit_Mask(MFRC522_FIFOLevelReg,0x80);
    for (i = 0; i < in_len_byte; i ++)
    {
        Write_NFC_One_Value(MFRC522_FIFODataReg, in_data[i]);
    }
    Write_NFC_One_Value(MFRC522_CommandReg, MFRC522_PCD_CALCCRC);
    i = 5;
    do
    {
        vTaskDelay(5 / portTICK_PERIOD_MS);
        n = Read_NFC_One_Value(MFRC522_DivIrqReg);
        i--;
    } while ((i != 0) && ! (n & 0x04));
    out_data[0] = Read_NFC_One_Value(MFRC522_CRCResultRegL);
    out_data[1] = Read_NFC_One_Value(MFRC522_CRCResultRegM);		
}

/* 选定指定UID的卡 */
uint8_t MFRC522_Select_Tag_Card(uint8_t* in_uid)
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN]; 
    uint32_t backBits;
    
    buffer[0] = MFRC522_PICC_ANTICOLL1;
    buffer[1] = 0x70;
    buffer[6] = 0;

    for (uint8_t i = 0; i < 4; i++)
    {
        buffer[i + 2] = in_uid[i];
        buffer[6] ^= in_uid[i];
    }
    
    MFRC522_Calulate_CRC(buffer, 7, & buffer[7]);
    MFRC522_Clr_Bit_Mask(MFRC522_Status2Reg, 0x08);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 9, buffer, &backBits);
    if ((status == MI_OK) && (backBits == 24))
        status = MI_OK;
    else
        status = MI_ERR;    
    return status;
}

/**
  * @brief  验证卡片密码
  * @param  Auth_mode，密码验证模式= 0x60，验证A密钥，
            密码验证模式= 0x61，验证B密钥
  * @param  block_addr，块地址
  * @param  Key，密码 
  * @param  uid，卡片序列号，4字节
  * @retval 状态值= MI_OK，成功
  */
uint8_t MRC522_Tag_Card_Auth(uint8_t auth_mode, uint8_t block_addr, uint8_t* in_key, uint8_t* in_uid)
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN];
    uint32_t backBits;
    
    /* 验证命令和块地址 */
    buffer[0] = auth_mode;
    buffer[1] = block_addr;
    /* 密码 */
    memcpy(&buffer[2], in_key, 6);
    /* 卡片序列号 */
    memcpy(&buffer[8], in_uid, 6);

    status = MFRC522_To_Card(MFRC522_PCD_AUTHENT, buffer, 12, buffer, &backBits);
    if ((status != MI_OK) || (!(Read_NFC_One_Value(MFRC522_Status2Reg) & 0x08)))
        status = MI_ERR;   
        
    return status;
}

/* 写指定的块数据 */
uint8_t MFRC522_Write_Block(uint8_t block_addr, uint8_t in_data[16])
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN];
    uint32_t backBits;
    
    buffer[0] = MFRC522_PICC_WRITE;
    buffer[1] = block_addr;
    MFRC522_Calulate_CRC(buffer, 2, & buffer[2]);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 4, buffer, &backBits);

    if ((status != MI_OK) || (backBits != 4) || ((buffer[0] & 0x0F) != 0x0A))
    {
        status = MI_ERR;   
    }
        
    if (status == MI_OK)
    {
        memcpy(buffer, in_data, 16);//按照16字节写入
        MFRC522_Calulate_CRC(buffer, 16, &buffer[16]);
        status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 18, buffer, &backBits);
        
        if ((status != MI_OK) || (backBits != 4) ||((buffer[0] & 0x0F) != 0x0A))
            status = MI_ERR;
    } 	
    return status;
}

/* 读指定的块数据 */
uint8_t MFRC522_Read_Block(uint8_t block_addr, uint8_t out_data[16])
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN]; 
    uint32_t backBits;
    
    buffer[0] = MFRC522_PICC_READ;
    buffer[1] = block_addr;
    MFRC522_Calulate_CRC(buffer, 2, &buffer[2]);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 4, buffer, &backBits);

    if ((status == MI_OK) && (backBits == 144))
        memcpy(out_data, buffer, 16);
    else
        status = MI_ERR;   
    
    return status;
}

/* 判断是否数据块 */
uint8_t MFRC522_Is_Data_Block(uint8_t block_addr)
{
    block_addr++;
    return (block_addr & 0x03) ? MI_OK : MI_ERR;
}

/* 标签卡休眠 */
uint8_t MFRC522_Tag_Card_Halt(void)
{
    uint8_t status;
	uint8_t buffer[MFRC522_MAXRLEN]; 
	uint32_t backBits;
  
    buffer[0] = MFRC522_PICC_HALT;
    buffer[1] = 0;
    MFRC522_Calulate_CRC(buffer, 2, &buffer[2]);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 4, buffer, &backBits);
    return status == MI_OK ? MI_OK : MI_ERR;
}




/* 增强功能 */

/* 获取固件版本 */
uint8_t MFRC522_Get_Firmware_Version(void)
{
    uint8_t response = Read_NFC_One_Value(MFRC522_VersionReg);
    
    printf("MFRC522 Firmware Version: 0x%02X\r\n", response);
    if (response == 0x90)
    {
        printf("MFRC522_v1\r\n");
    }
    else if (response == 0x91)
    {
        printf("MFRC522_v2\r\n");
    }
    else if (response == 0x92)
    {
        printf("MFRC522_v3\r\n");
    }
    else if (response == 0x88)
    {
        printf("MFRC522 clone detected\r\n");
    }
    else
    {
        printf("Unknown firmware version\r\n");
    }

    return response;
}

/* 检查是否有新卡出现 */
uint8_t MFRC522_Is_New_Card_Present(void)
{
    uint8_t status;
    uint8_t InData;
    uint8_t buffer[2];
    uint32_t backBits;
    
    // REQIDL = find cards in sleep mode
    InData = MFRC522_PICC_REQIDL;
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, &InData, 1, buffer, &backBits);
    if (status == MI_OK || status == MI_NOTAGERR)
    {
        return MI_OK;
    }
    return MI_ERR;
}

/* 获取卡片类型 */
uint8_t MFRC522_Get_Card_Type(uint8_t* buffer)
{
    if (buffer[0] == 0x04 && buffer[1] == 0x00) return PICC_TYPE_MIFARE_MINI;
    if (buffer[0] == 0x04 && buffer[1] == 0x08) return PICC_TYPE_MIFARE_1K;
    if (buffer[0] == 0x02 && buffer[1] == 0x00) return PICC_TYPE_MIFARE_4K;
    if (buffer[0] == 0x04 && buffer[1] == 0x03) return PICC_TYPE_MIFARE_UL;
    if (buffer[0] == 0x04 && buffer[1] == 0x10) return PICC_TYPE_MIFARE_PLUS;
    if (buffer[0] == 0x04 && buffer[1] == 0x80) return PICC_TYPE_MIFARE_DESFIRE;
    if (buffer[0] == 0x05 && buffer[1] == 0x01) return PICC_TYPE_TNP3XXX;
    return PICC_TYPE_NOT_COMPLETE;
}


/* 处理增值/减值的公共逻辑 */
static uint8_t MFRC522_AdjustValue(uint8_t command, uint8_t block_addr, uint32_t value)
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN];
    uint32_t backBits;
    
    // 发送命令
    buffer[0] = command;
    buffer[1] = block_addr;
    MFRC522_Calulate_CRC(buffer, 2, &buffer[2]);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 4, buffer, &backBits);
    
    // 发送调整值
    if (status == MI_OK)
    {
        buffer[0] = (value >> 24) & 0xFF;
        buffer[1] = (value >> 16) & 0xFF;
        buffer[2] = (value >>  8) & 0xFF;
        buffer[3] = (value >>  0) & 0xFF;
        MFRC522_Calulate_CRC(buffer, 4, &buffer[4]);
        status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 6, buffer, &backBits);
    }
    
    return status;
}
/* 增值操作 */
uint8_t MFRC522_Increment(uint8_t block_addr, uint32_t value)
{
    return MFRC522_AdjustValue(MFRC522_PICC_INCREMENT, block_addr, value);
}
/* 减值操作 */
uint8_t MFRC522_Decrement(uint8_t block_addr, uint32_t value)
{
    return MFRC522_AdjustValue(MFRC522_PICC_DECREMENT, block_addr, value);
}

/* 处理简单命令的公共逻辑 */
static uint8_t MFRC522_Send_Simple_Command(uint8_t command, uint8_t block_addr)
{
    uint8_t status;
    uint8_t buffer[MFRC522_MAXRLEN];
    uint32_t backBits;
    
    buffer[0] = command;
    buffer[1] = block_addr;
    MFRC522_Calulate_CRC(buffer, 2, &buffer[2]);
    status = MFRC522_To_Card(MFRC522_PCD_TRANSCEIVE, buffer, 4, buffer, &backBits);
    
    return status;
}
/* 恢复操作 - 将块中的值加载到内部数据寄存器 */
uint8_t MFRC522_Restore(uint8_t block_addr)
{
    return MFRC522_Send_Simple_Command(MFRC522_PICC_RESTORE, block_addr);
}
/* 传输操作 - 将内部数据寄存器的值存储到块中 */
uint8_t MFRC522_Transfer(uint8_t block_addr)
{
    return MFRC522_Send_Simple_Command(MFRC522_PICC_TRANSFER, block_addr);
}

/* 软件断电 */
void MFRC522_Soft_Power_Down(void)
{
    Write_NFC_One_Value(MFRC522_CommandReg, MFRC522_PCD_IDLE);
    MFRC522_Antenna_Off();
}

/* 软件上电 */
void MFRC522_Soft_Power_Up(void)
{
    MFRC522_Antenna_On();
    vTaskDelay(5 / portTICK_RATE_MS);
}

/* 获取4块的访问位 */
static void Mifare_One_Get_Ctrl_Bits(uint8_t in_ctrl_word[4], Mifare_One_Ctrl_Bits_t out_ctrl_bits[4])
{
    // 定义每块的位位置
    const uint8_t bit_positions[4][3] =
    {
        {6, 2, 4},  // 块0: C1在字节6位6, C2在字节7位2, C3在字节8位4
        {5, 1, 3},  // 块1: C1在字节6位5, C2在字节7位1, C3在字节8位3
        {4, 0, 2},  // 块2: C1在字节6位4, C2在字节7位0, C3在字节8位2
        {7, 3, 5},  // 块3: C1在字节6位7, C2在字节7位3, C3在字节8位5
    };

    // 提取对应位的值
    for (int block = 0; block < 4; block++)
    {
        out_ctrl_bits[block].C1 = (in_ctrl_word[0] >> bit_positions[block][0]) & 1;
        out_ctrl_bits[block].C2 = (in_ctrl_word[1] >> bit_positions[block][1]) & 1;
        out_ctrl_bits[block].C3 = (in_ctrl_word[2] >> bit_positions[block][2]) & 1;
    }
}

/* 获取4字节控制字 */
static void Mifare_One_Get_Ctrl_Word(uint8_t out_ctrl_word[4], Mifare_One_Ctrl_Bits_t in_ctrl_bits[4])
{
    memset(out_ctrl_word, 0, 4);
    
    // 生成控制字字节6-9
    for (size_t i = 0; i < 4; i++)
    {
        // 字节6: C10-C13 (位0-3), C20-C23 (位4-7) [取反]
        out_ctrl_word[0] |= (in_ctrl_bits[i].C1 & 0x01) << i;
        out_ctrl_word[0] |= (in_ctrl_bits[i].C2 & 0x01) << (i + 4);

        // 字节7: C13-C10 (位7-4), C23-C20 (位3-0)
        out_ctrl_word[1] |= (in_ctrl_bits[i].C1 & 0x01) << (7 - i);
        out_ctrl_word[1] |= (in_ctrl_bits[i].C2 & 0x01) << (3 - i);

        // 字节8: C33-C30 (位7-4), ~C33-~C30 (位3-0)
        out_ctrl_word[2] |= (in_ctrl_bits[i].C3 & 0x01) << (7 - i);
        out_ctrl_word[2] |= ((~in_ctrl_bits[i].C3) & 0x01) << (3 - i);

        // 字节9: ~C13-~C10 (位7-4), C33-C30 (位3-0)
        out_ctrl_word[3] |= ((~in_ctrl_bits[i].C1) & 0x01) << (7 - i);
        out_ctrl_word[3] |= (in_ctrl_bits[i].C3 & 0x01) << (3 - i);
    }
    
    // 字节6需要整体取反
    out_ctrl_word[0] = ~out_ctrl_word[0];

    /*
    // 字节6: ~C23, ~C22, ~C21, ~C20, ~C13, ~C12, ~C11, ~C10
    out_ctrl_word[0] = ~((in_ctrl_bits[3].C2 << 7) | (in_ctrl_bits[2].C2 << 6) | (in_ctrl_bits[1].C2 << 5) | (in_ctrl_bits[0].C2 << 4) | (in_ctrl_bits[3].C1 << 3) | (in_ctrl_bits[2].C1 << 2) | (in_ctrl_bits[1].C1 << 1) | in_ctrl_bits[0].C1);
    // 字节7: C13, C12, C11, C10, C23, C22, C21, C20
    out_ctrl_word[1] = (in_ctrl_bits[3].C1 << 7) | (in_ctrl_bits[2].C1 << 6) | (in_ctrl_bits[1].C1 << 5) | (in_ctrl_bits[0].C1 << 4) | (in_ctrl_bits[3].C2 << 3) | (in_ctrl_bits[2].C2 << 2) | (in_ctrl_bits[1].C2 << 1) | in_ctrl_bits[0].C2;
    // 字节8: C33, C32, C31, C30, ~C33, ~C32, ~C31, ~C30
    out_ctrl_word[2] = (in_ctrl_bits[3].C3 << 7) | (in_ctrl_bits[2].C3 << 6) | (in_ctrl_bits[1].C3 << 5) | (in_ctrl_bits[0].C3 << 4) | (~in_ctrl_bits[3].C3 << 3) | (~in_ctrl_bits[2].C3 << 2) | (~in_ctrl_bits[1].C3 << 1) | ~in_ctrl_bits[0].C3;
    // 字节9: ~C13, ~C12, ~C11, ~C10, C33, C32, C31, C30
    out_ctrl_word[3] = (~in_ctrl_bits[3].C1 << 7) | (~in_ctrl_bits[2].C1 << 6) | (~in_ctrl_bits[1].C1 << 5) | (~in_ctrl_bits[0].C1 << 4) | (in_ctrl_bits[3].C3 << 3) | (in_ctrl_bits[2].C3 << 2) | (in_ctrl_bits[1].C3 << 1) | in_ctrl_bits[0].C3;
    */
}

/* 更新控制字 */
void Mifare_One_Update_Ctrl_Word(uint8_t block_addr, Mifare_One_Access_Rights_enum access_rights, uint8_t src_ctrl_word[4], uint8_t dst_ctrl_word[4])
{
    uint8_t block;
    Mifare_One_Ctrl_Bits_t Mifare_One_Ctrl_Bits[4];

    Mifare_One_Get_Ctrl_Bits(src_ctrl_word, Mifare_One_Ctrl_Bits);

    block = block_addr & 0x03;
    Mifare_One_Ctrl_Bits[block].C1 = (access_rights >> 2) & 1;
    Mifare_One_Ctrl_Bits[block].C2 = (access_rights >> 1) & 1;
    Mifare_One_Ctrl_Bits[block].C3 = (access_rights >> 0) & 1;

    Mifare_One_Get_Ctrl_Word(dst_ctrl_word, Mifare_One_Ctrl_Bits);
}

/* 获取块的访问权限 */
Mifare_One_Access_Rights_enum Mifare_One_Get_Block_Rights(uint8_t block_addr, uint8_t src_ctrl_word[4])
{
    uint8_t block;
    Mifare_One_Ctrl_Bits_t Mifare_One_Ctrl_Bits[4];

    Mifare_One_Get_Ctrl_Bits(src_ctrl_word, Mifare_One_Ctrl_Bits);

    block = block_addr & 0x03;
    return  (Mifare_One_Access_Rights_enum)(Mifare_One_Ctrl_Bits[block].C1 << 2 | Mifare_One_Ctrl_Bits[block].C2 << 1 | Mifare_One_Ctrl_Bits[block].C3 << 0);
}




/* 打印MIFARE Classic 1K卡内容到串口 */
void MFRC522_Dump_Classic_1K_To_Serial(Mifare_S50_t* out_data, uint8_t *in_uid)
{
    uint8_t status;
    uint8_t block_addr;
    
    printf("\n\nMIFARE Classic 1K Dump:\r\n");
    printf("+--------+-------------------------------------------------+\r\n");
    printf("| Block  | 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  |\r\n");
    printf("+--------+-------------------------------------------------+\r\n");

    // 16个扇区，每个扇区4个块
    for (size_t i = 0; i < 16; i++)
    {
        block_addr = i << 2;
        status = MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1B, block_addr, out_data->Sector[i].Password_B, in_uid);
        for (size_t j = 0; j < 4; j++)
        {
            printf("| S%02dB%02d | ", i, j);
            if (status == MI_OK)
            {
                status = MFRC522_Read_Block(block_addr + j, out_data->Sector[i].Block_Data[j]);
                if (status == MI_OK)
				{
                    for (size_t count = 0; count < 16; count++)
                    {
                        printf("%02X ", out_data->Sector[i].Block_Data[j][count]);
                    }
				}
                else
                {
                    printf("Read failed");
                }
            }
            else
            {
                printf("Authentication failed");
            }
            printf("|\r\n");
        }
        printf("+--------+-------------------------------------------------+\r\n");
    }
}

/* 打印MIFARE Classic 4K卡内容到串口 */
void MFRC522_Dump_Classic_4K_To_Serial(uint8_t *in_uid)
{
    uint8_t status;
    uint8_t block_addr;
    uint8_t buffer[16];
    uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // 默认密钥
    
    printf("\n\nMIFARE Classic 4K Dump:\n");
    printf("+--------+-------------------------------------------------+\n");
    printf("| Block  | 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  |\n");
    printf("+--------+-------------------------------------------------+\n");
    
    // 前32个扇区，每个扇区4个块
    for (size_t i = 0; i < 32; i++)
    {
        block_addr = i << 2;
        status = MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1B, block_addr, key, in_uid);
        for (size_t j = 0; j < 4; j++)
        {
            printf("| S%02dB%02d | ", i, j);
            if (status == MI_OK)
            {
                status = MFRC522_Read_Block(block_addr + j, buffer);
                if (status == MI_OK)
				{
                    for (size_t count = 0; count < 16; count++)
                    {
                        printf("%02X ", buffer[count]);
                    }
				}
                else
                {
                    printf("Read failed");
                }
            }
            else
            {
                printf("Authentication failed");
            }
            printf("|\r\n");
        }
        printf("+--------+-------------------------------------------------+\r\n");
    }

    // 最后8个扇区，每个扇区16个块
    for (size_t i = 32; i < 40; i++)
    {
        for (size_t j = 0; j < 16; j++)
        {
            block_addr = 128 + (i - 32) * 16 + j;
            
            // 验证扇区尾部的密钥
            if (j == 15)
            {
                status = MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1A, block_addr, key, in_uid);
            }
            else
            {
                // 如果是第一个块，并且还没有验证过
                if (block_addr == 128)
                {
                    status = MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1A, block_addr, key, in_uid);
                }
            }
            printf("| S%02dB%02d | ", i, j);
            if (status == MI_OK)
            {
                status = MFRC522_Read_Block(block_addr, buffer);
                if (status == MI_OK)
                {
                    for (size_t count = 0; count < 16; count++)
                    {
                        printf("%02X ", buffer[count]);
                    }
                }
                else
                {
                    printf("Read failed                               ");
                }
            }
            else
            {
                printf("Authentication failed                     ");
            }
            printf("|\n");
        }
        printf("+--------+-------------------------------------------------+\n");
    }
}

/* 修改密码A */
uint8_t MFRC522_Change_KeyA(uint8_t block_addr, uint8_t* in_uid, uint8_t in_KeyB[6], uint8_t new_KeyA[6])
{
    uint8_t buffer[MFRC522_MAXRLEN];


    block_addr = block_addr / 4 * 4 + 3;
    /* 校验 B 密码 */
    if (MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1B, block_addr, in_KeyB, in_uid) == MI_OK)
    {
        // 读取控制块里原本的数据（只要修改密码A，其他数据不改）
        if (MFRC522_Read_Block(block_addr, buffer) == MI_OK)
        {
            /* 修改密码A */
            memcpy(buffer, new_KeyA, 6);
            return MFRC522_Write_Block(block_addr, buffer);
        }
    }

    return MI_ERR;
}

/* 修改密码B */
uint8_t MFRC522_Change_KeyB(uint8_t block_addr, uint8_t* in_uid, uint8_t in_KeyB[6], uint8_t new_KeyB[6])
{
    uint8_t buffer[MFRC522_MAXRLEN];


    block_addr = block_addr / 4 * 4 + 3;
    /* 校验 B 密码 */
    if (MRC522_Tag_Card_Auth(MFRC522_PICC_AUTHENT1B, block_addr, in_KeyB, in_uid) == MI_OK)
    {
        // 读取控制块里原本的数据（只要修改密码A，其他数据不改）
        if (MFRC522_Read_Block(block_addr, buffer) == MI_OK)
        {
            /* 修改密码B */
            memcpy(buffer + 6 + 4, new_KeyB, 6);
            return MFRC522_Write_Block(block_addr, buffer);
        }
    }

    return MI_ERR;
}
